#include "biplTypes.h"
#include <iostream>
#include <sstream>

/// implicitly convert to bool
floatTypes::operator bool() const
{
	//return bool(val);
	if ( val == 0.0f )
		return false;
	else
		return true;
}

/// implicitly convert to other types
 floatTypes::operator const degreeTypes() const
{
	return toDegree();
}

floatTypes::operator const pairTypes() const
{
	return toPair();
}

floatTypes::operator const stringTypes() const
{
	return toString();
}

/// output stream operator
std::ostream&
	operator<<(std::ostream&out, const floatTypes& s)
{
	out << s.val;
	return out;
}

/// Negation Operator
floatTypes operator- (const floatTypes &s)
{
	return floatTypes(-s.val);
}

/// Arithmetic Operators
const floatTypes operator+(const floatTypes& lhs, const floatTypes& rhs)
{
	return floatTypes(lhs.val + rhs.val);
}

const floatTypes operator-(const floatTypes& lhs, const floatTypes& rhs)
{
	return floatTypes(lhs.val - rhs.val);
}

const floatTypes operator/(const floatTypes& lhs, const floatTypes& rhs)
{
	return floatTypes(lhs.val / rhs.val);
}

const floatTypes operator*(const floatTypes& lhs, const floatTypes& rhs)
{
	return floatTypes(lhs.val * rhs.val);
}

const floatTypes operator%(const floatTypes& lhs, const floatTypes& rhs)
{
	return floatTypes(fmod(lhs.val, rhs.val));
}

/// Arithmetic Assignment Operators
floatTypes& operator+=(floatTypes& lhs, const floatTypes& rhs)
{
	lhs.val += rhs.val;
	return lhs;
}

floatTypes& operator-=(floatTypes& lhs, const floatTypes& rhs)
{
	lhs.val -= rhs.val;
	return lhs;
}

floatTypes& operator*=(floatTypes& lhs, const floatTypes& rhs)
{
	lhs.val *= rhs.val;
	return lhs;
}

floatTypes& operator/=(floatTypes& lhs, const floatTypes& rhs)
{
	lhs.val /= rhs.val;
	return lhs;
}

floatTypes& operator%=(floatTypes& lhs, const floatTypes& rhs)
{
	lhs.val = fmod (lhs.val, rhs.val);
	return lhs;
}

/// Equality Operators
boolTypes operator==(const boolTypes& left, const floatTypes& right)
{
	return boolTypes(left == right.toBoolean());
}

boolTypes operator!=(const boolTypes& left, const floatTypes& right)
{
	return boolTypes(left != right.toBoolean());
}

boolTypes operator==(const floatTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() == right);
}

boolTypes operator!=(const floatTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() != right);
}

boolTypes operator==(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val == right.val);
}

boolTypes operator!=(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val != right.val);
}

/// Relational Operators
boolTypes operator<(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val < right.val);
}

boolTypes operator>(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val > right.val);
}

boolTypes operator<=(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val <= right.val);
}

boolTypes operator>=(const floatTypes& left, const floatTypes& right)
{
	return boolTypes(left.val >= right.val);
}

/// Logical Operators
boolTypes operator!(const floatTypes& s)
{
	return !s.toBoolean();
}

boolTypes operator&&(const floatTypes& left, const floatTypes& right)
{
	return left.toBoolean() && right.toBoolean();
}

boolTypes operator||(const floatTypes& left, const floatTypes& right)
{
	return left.toBoolean() || right.toBoolean();
}

/// Type conversion functions
boolTypes floatTypes::toBoolean() const
{
	if ( val == 0.0f )
		return boolTypes(false);
	else
		return boolTypes(true);
}

intTypes floatTypes::toInteger() const
{
	return intTypes(int(val));
}

floatTypes floatTypes::toFloat() const
{
	return floatTypes(val);
}

degreeTypes floatTypes::toDegree() const
{
	return degreeTypes(val);
}

pairTypes floatTypes::toPair() const
{
	return pairTypes(val, val);
}

stringTypes floatTypes::toString() const
{
	std::stringstream ss(std::stringstream::in | std::stringstream::out);
	ss << val;
	
	return stringTypes(ss.str());
}